import serial.tools.list_ports
import winreg
import os


class SerialManager:
    def __init__(self, log_callback=None):
        self.serial_port = None
        self.log_callback = log_callback

    def get_available_ports(self):
        """
        返回一个列表，包含当前系统所有可用的串口标识符
        使用纯Python实现，避免调用外部命令
        """
        ports = []

        try:
            # 获取标准COM端口
            available_ports = serial.tools.list_ports.comports()
            ports = [port.device for port in available_ports]

            # 添加从注册表检测的虚拟串口
            ports.extend(self.get_virtual_ports_from_registry())

            # 去重并排序
            ports = list(set(ports))
            ports.sort(key=lambda x: int(x[3:]) if x[3:].isdigit() else float('inf'))

        except Exception as e:
            print(f"获取串口列表时出错: {e}")
            # 回退到基本方法
            ports = [f"COM{i}" for i in range(1, 257)]

        return ports

    def get_virtual_ports_from_registry(self):
        """
        从注册表获取虚拟串口，避免调用外部命令
        """
        virtual_ports = []
        # registry_paths = [
        #     r"SYSTEM\CurrentControlSet\Enum",
        #     r"SYSTEM\CurrentControlSet\Control\COM Name Arbiter"
        # ]

        try:
            # 方法1: 从COM Name Arbiter获取
            try:
                key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,
                                     r"SYSTEM\CurrentControlSet\Control\COM Name Arbiter")
                i = 0
                while True:
                    try:
                        value_name, value_data, _ = winreg.EnumValue(key, i)
                        if value_name.startswith("COM"):
                            virtual_ports.append(value_name)
                        i += 1
                    except WindowsError:
                        break
                winreg.CloseKey(key)
            except:
                pass

            # 方法2: 从设备枚举获取
            try:
                key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,
                                     r"SYSTEM\CurrentControlSet\Enum")
                i = 0
                while True:
                    try:
                        subkey_name = winreg.EnumKey(key, i)
                        if "COM" in subkey_name or "VSPD" in subkey_name:
                            subkey = winreg.OpenKey(key, subkey_name)
                            j = 0
                            while True:
                                try:
                                    port_key_name = winreg.EnumKey(subkey, j)
                                    if port_key_name.startswith("COM"):
                                        virtual_ports.append(port_key_name)
                                    j += 1
                                except WindowsError:
                                    break
                            winreg.CloseKey(subkey)
                        i += 1
                    except WindowsError:
                        break
                winreg.CloseKey(key)
            except:
                pass

        except Exception as e:
            print(f"从注册表获取虚拟串口时出错: {e}")

        return list(set(virtual_ports))

    def connect(self, port, baudrate=9600, bytesize=8, stopbits=1, parity='N'):
        """连接串口"""
        try:
            self.serial_port = serial.Serial(
                port=port,
                baudrate=baudrate,
                bytesize=bytesize,
                stopbits=stopbits,
                parity=parity,
                timeout=1
            )
        except Exception as e:
            raise Exception(f"串口连接失败: {str(e)}")

    # 其他方法保持不变...
    def disconnect(self):
        """断开串口连接"""
        if self.serial_port and self.serial_port.is_open:
            self.serial_port.close()
        self.serial_port = None

    def is_connected(self):
        """检查是否已连接"""
        return self.serial_port is not None and self.serial_port.is_open

    def read_data(self):
        """读取数据"""
        if not self.is_connected():
            return None

        try:
            if self.serial_port.in_waiting > 0:
                data = self.serial_port.read(self.serial_port.in_waiting)
                if self.log_callback and data:
                    self.log_callback("Rx", data)
                return data
            else:
                return None
        except Exception as e:
            raise Exception(f"数据读取错误: {str(e)}")

    def send_command(self, command):
        """发送命令"""
        if not self.is_connected():
            raise Exception("串口未连接")

        try:
            data_to_send = f"{command}\r\n".encode()
            self.serial_port.write(data_to_send)
            if self.log_callback:
                self.log_callback("Tx", data_to_send)
        except Exception as e:
            raise Exception(f"命令发送失败: {str(e)}")